package com.darknight.ftp.connection.pool;

import com.darknight.ftp.connection.FtpUserConnection;
import org.springframework.util.Assert;

import java.io.IOException;
import java.util.Map;
import java.util.Stack;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by DarKnight on 2017/7/30.
 */
public class ConnectionPool {
    private static final Integer SIZE_DEFAULT_VALUE = 10;

    private Integer poolSize = SIZE_DEFAULT_VALUE;
//    private Stack<FtpUserConnection> connectionStack = new Stack<FtpUserConnection>();
    private Map<String, Stack<FtpUserConnection>> poolContent = new ConcurrentHashMap<String, Stack<FtpUserConnection>>();

    public ConnectionPool() {
    }

    public Integer getPoolSize() {
        return poolSize;
    }

    public void setPoolSize(Integer poolSize) {
        this.poolSize = poolSize;
    }

    public boolean isNotEmptyPool() {
        for(String connectionAddress : poolContent.keySet()) {
            Stack<FtpUserConnection> connectionStack = poolContent.get(connectionAddress);
            if(connectionStack != null && !connectionStack.isEmpty()) {
                return true;
            }
        }

        return false;
    }

    public boolean isEmptyPool() {
        return !isNotEmptyPool();
    }

    public boolean hasConnection(String connectionAddress) {
        Assert.hasText(connectionAddress, "连接地址不能为空");

        if(isNotEmptyPool()) {
            Stack<FtpUserConnection> connectionStack = poolContent.get(connectionAddress);

            if(connectionStack != null && !connectionStack.isEmpty()) {
                return true;
            }
        }

        return false;
    }

    public boolean hasConnection(String ftpAddress, Integer ftpPort) {
        Assert.hasText(ftpAddress, "连接地址不能为空");
        Assert.notNull(ftpPort, "连接端口不能为空");

        String connectionAddress = ftpAddress + ":" + ftpPort;

        return hasConnection(connectionAddress);
    }

    public void addConnection(FtpUserConnection connection) {
        Assert.notNull(connection, "待添加连接不能为空");

        String connectionAddress = connection.getFtpHostName() + ":" + connection.getFtpPort();
        Stack<FtpUserConnection> connectionStack = poolContent.get(connectionAddress);

        if(connectionStack == null) {
            connectionStack = new Stack<FtpUserConnection>();
        }
        connectionStack.push(connection);
        poolContent.put(connectionAddress, connectionStack);
    }

    public FtpUserConnection getConnection(String connectionAddress) {
        Assert.hasText(connectionAddress, "连接地址不能为空");
        Assert.isTrue(hasConnection(connectionAddress), "目标地址连接为空，无法获取连接");

        Stack<FtpUserConnection> connectionStack = poolContent.get(connectionAddress);

        return connectionStack.pop();
    }

    public FtpUserConnection getConnection(String ftpAddress, Integer ftpPort) {
        Assert.hasText(ftpAddress, "连接地址不能为空");
        Assert.notNull(ftpPort, "连接端口不能为空");

        String connectionAddress = ftpAddress + ":" + ftpPort;

        return getConnection(connectionAddress);
    }

    public void releaseAllConnection() throws IOException {
        Assert.isTrue(isNotEmptyPool(), "连接池为空，没有可释放的连接");

        FtpUserConnection connection;

        for(String connectionAddress : poolContent.keySet()) {
            Stack<FtpUserConnection> connectionStack = poolContent.get(connectionAddress);
            if(connectionStack != null && !connectionStack.isEmpty()) {
                connection = connectionStack.pop();
                connection.disconnect();
            }
        }
    }
}
